//
//  BrwoserContentView.m
//  CLBrowser
//
//  Created by 梁慧聪 on 2016/10/9.
//  Copyright © 2021年 梁慧聪. All rights reserved.
//

#import "CLWebContainerView.h"
#import "CLWebViewManager.h"
#import "CLWebDataView.h"
#import "CLHttpHelper.h"
#import "NSURL+CLUtility.h"
#import "NSString+CLUtility.h"
#import "NSURLCache+CLUtility.h"
#import "CLDelegateManager+WebViewDelegate.h"
#import "CLSessionData.h"
#import "CLWebServer.h"
#import "CLVCMain.h"
#import "CLHTTPClient.h"
#import "CLFindInPageBar.h"
#import "CLMenuHelper.h"
#import "CLArrowActivityView.h"
#import "CLGestureProxy.h"
#import "NSData+CLUtility.h"
#import "UIAlertAction+CLUtility.h"
#import "CLHomePageView.h"
#import "CLExtentionsManager.h"
#import <Photos/Photos.h>
#import "CLReadMainController.h"
static CGFloat const kArrowActivitySize = 30.f;
static NSInteger const kActionSheetTitleMaxLength = 120;
static NSString *const kBaiduSearchPath = @"https://m.baidu.com/s?ie=utf-8&word=";

@interface CLWebContainerView () <WebViewDelegate, MenuHelperInterface, CLBrowserLoadURLDelegate, CLWebViewDelegate, CLFindInPageBarDelegate>

@property (nonatomic, readwrite, weak) CLWebView *webView;
@property (nonatomic, weak) UIGestureRecognizer *selectionGestureRecognizer;
@property (nonatomic, strong) CLGestureProxy *gestureProxy;
@property (nonatomic, assign) CGPoint edgeStartPoint;
@property (nonatomic, strong) CLArrowActivityView *arrowActivityView;
@property (nonatomic, assign) BOOL showActivityView;

@end

@implementation CLWebContainerView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setupWebView];
    }
    return self;
}

- (UIScrollView *)scrollView {
    return self.webView.scrollView;
}

- (void)setupWebView {
    [CLWebViewManager sharedInstance].clContainerView = self;
    [self restoreWithCompletionHandler:nil animation:NO];
    [[CLDelegateManager sharedInstance] registerDelegate:self forKeys:@[kDelegateManagerBrowserContainerLoadURL, kDelegateManagerWebView, kDelegateManagerFindInPageBarDelegate]];
    [[CLDelegateManager sharedInstance] addWebViewDelegate:self];
    [Notifier addObserver:self selector:@selector(handleOpenInNewWindow:) name:kOpenInNewWindowNotification object:nil];
    
    [self addScreenEdgePanGesture];
    self.restorationIdentifier = NSStringFromClass([self class]);
}

- (void)startLoadWebViewWithURL:(NSString *)url {
    if ([[NSURL URLWithString:url] isErrorPageURL]) {
        NSURL *originalUrl = [[NSURL URLWithString:url] originalURLFromErrorURL];
        url = originalUrl.absoluteString;
    }
    
    [self startLoadWithWebView:self.webView url:[NSURL URLWithString:url]];
}

- (void)startLoadWithWebView:(CLWebView *)webView url:(NSURL *)url {
    [self removeHomePageIfNeededWithWebView:webView url:url needsEqual:NO];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];
}

- (void)removeHomePageIfNeededWithWebView:(CLWebView *)webView url:(NSURL *)url needsEqual:(BOOL)needsEqual {
    BOOL isNeeds = needsEqual ? [url.absoluteString isEqualToString:DEFAULT_CARD_CELL_URL] : ![url.absoluteString isEqualToString:DEFAULT_CARD_CELL_URL];
    if (webView.homePage && isNeeds) {
        [webView.homePage removeFromSuperview];
        webView.homePage = nil;
        NSArray<WeakCLBrowserDelegate *> *delegates = [[CLDelegateManager sharedInstance] webViewDelegates];
        foreach(delegate, delegates) {
            if ([delegate.delegate respondsToSelector:@selector(webView:hiddenTopBar:)]) {
                [delegate.delegate webView:webView hiddenTopBar:NO];
            }
        }
    }
}

- (void)handleOpenInNewWindow:(NSNotification *)notify {
    NSURL *url = [notify.userInfo objectForKey:@"url"];
    if ([url isKindOfClass:[NSURL class]]) {
        [self handleOpenInNewWindowWithURL:url];
    }
}

- (void)handleOpenInNewWindowWithURL:(NSURL *)url {
    WEAK_SELF;
    [[CLWebViewManager sharedInstance] addWebModelWithURL:url completion:^{
        STRONG_SELF;
        if (strongSelf) {
            [strongSelf restoreWithCompletionHandler:^(CLWebModel *webModel, CLWebView *webView) {
                NSNotification *notify = [NSNotification notificationWithName:kWebTabSwitch object:self userInfo:@{@"webView":webView}];
                [Notifier postNotification:notify];
            } animation:YES];
        }
    }];
}

- (void)restoreWithCompletionHandler:(CLTabCompletion)completion animation:(BOOL)animation {
    WEAK_SELF;
    [[CLWebViewManager sharedInstance] setCurWebViewOperationBlockWith:^(CLWebModel *webModel, CLWebView *webView){
        NSLog(@"Multi：<切换> %@,%@,url:%@,%@",webModel.title,webModel.imageKey,webModel.url,webView.request.URL);
        foreach(delegate, [[CLDelegateManager sharedInstance] webViewDelegates]) {
            if ([delegate.delegate respondsToSelector:@selector(webView:hiddenTopBar:)]) {
                [delegate.delegate webView:webView hiddenTopBar:NO];
            }
        }
        STRONG_SELF;
        if (strongSelf) {
            CLWebView *oldBrowserView = strongSelf.webView;
            
            webView.transform = CGAffineTransformIdentity;
            webView.bounds = CGRectMake(0, 0, strongSelf.width, strongSelf.height);
            webView.center = strongSelf.center;
            
            if (oldBrowserView != webView && [oldBrowserView superview] && animation) {
                webView.transform = CGAffineTransformMakeTranslation(strongSelf.width, 0);
                oldBrowserView.transform = CGAffineTransformIdentity;
                // If the transform property is not the identity transform, the value of frame is undefined and therefore should be ignored.
                oldBrowserView.bounds = CGRectMake(0, 0, strongSelf.width, strongSelf.height);
                oldBrowserView.center = strongSelf.center;
                
                [UIView transitionWithView:strongSelf duration:.5f options:UIViewAnimationOptionCurveEaseInOut animations:^{
                    oldBrowserView.transform = CGAffineTransformMakeTranslation(- strongSelf.width, 0);
                    [strongSelf addSubview:webView];
                    webView.transform = CGAffineTransformIdentity;
                }completion:^(BOOL finished){
                    webView.bounds = CGRectMake(0, 0, strongSelf.width, strongSelf.height);
                    webView.center = strongSelf.center;
                    [oldBrowserView removeFromSuperview];
                }];
            } else if(oldBrowserView != webView) {
                [oldBrowserView removeFromSuperview];
                [strongSelf addSubview:webView];
            }
            
            strongSelf.webView = webView;
            if ([webModel.url isEqualToString:DEFAULT_CARD_CELL_URL]) {
                [strongSelf handleHomePageWithWebView:webView];
                return;
            }
            if (!webView.request) {
                CLSessionData *sessionData = webModel.sessionData;
                if (sessionData) {
                    NSDictionary *originalDic = sessionData.jsonDictionary;
                    NSArray *history = [originalDic cl_arrayForKey:@"history"];
                    if (history.count) {
                        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:originalDic options:0 error:NULL];
                        if (jsonData) {
                            NSString *escapedJSON = [jsonData jsonString];
                            escapedJSON = (escapedJSON) ? escapedJSON : @"";
                            NSURL *restoreURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/about/sessionrestore?history=%@",[[CLWebServer sharedInstance] base],escapedJSON]];
                            [strongSelf startLoadWithWebView:webView url:restoreURL];
                        } else {
                            [strongSelf startLoadWebViewWithURL:webModel.url];
                        }
                    } else {
                        [strongSelf startLoadWebViewWithURL:webModel.url];
                    }
                } else {
                    [strongSelf startLoadWebViewWithURL:webModel.url];
                }
            }
            CLSafeExecuteBlock(completion, webModel, webView);
        }
    }];
}

#pragma mark - Handle HomePage Load

- (void)handleHomePageWithWebView:(CLWebView *)webView {
    if (!webView.homePage) {
        CLHomePageView *homePage = [[CLHomePageView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height)];
        webView.homePage = homePage;
        [webView addSubview:homePage];
    }
    
    NSArray<WeakCLBrowserDelegate *> *delegates = [[CLDelegateManager sharedInstance] webViewDelegates];
    
    foreach(delegate, delegates) {
        if ([delegate.delegate respondsToSelector:@selector(webView:hiddenTopBar:)]) {
            [delegate.delegate webView:webView hiddenTopBar:YES];
        }
    }
    
    // remove wrong title when back to home page
    [[CLDelegateManager sharedInstance] performSelector:@selector(webView:gotTitleName:) arguments:@[webView,@""] key:kDelegateManagerWebView];
    if (![CLWebViewManager.sharedInstance imageFromDiskCacheForKey:DEFAULT_CARD_CELL_URL]) {
        [CLWebViewManager.sharedInstance storeImage:[self snapshotForBrowserWebView] forKey:DEFAULT_CARD_CELL_URL];
    }
}

#pragma mark - ActivityView

- (CLArrowActivityView *)arrowActivityView {
    if (!_arrowActivityView) {
        _arrowActivityView = [[CLArrowActivityView alloc] initWithFrame:CGRectMake(0, 0, kArrowActivitySize, kArrowActivitySize) kind:ArrowActivityKindLeft];
        [self insertSubview:_arrowActivityView atIndex:0];
    }
    return _arrowActivityView;
}

- (void)addArrowViewWithPoint:(CGPoint)point {
    if (!self.showActivityView) {
        return;
    }
    
    BOOL isLeft = point.x < self.width / 2.0f;
    if (isLeft) {
        self.arrowActivityView.center = CGPointMake(5.f + kArrowActivitySize / 2.0f, self.height / 2);
    }
    else{
        self.arrowActivityView.center = CGPointMake(self.width - kArrowActivitySize / 2.0f - 5.f, self.height / 2.0f);
    }
    
    [self.arrowActivityView setKind:(isLeft) ? ArrowActivityKindLeft : ArrowActivityKindRight];
}

- (void)removeArrowActivityView {
    [self.arrowActivityView removeFromSuperview];
    self.arrowActivityView = nil;
}

- (void)setShowActivityViewIfNeeded {
    NSUInteger num = [[CLWebViewManager sharedInstance] numberOfTabs];
    self.showActivityView = (num > 1);
}

- (BOOL)isWindowSwitchLeft {
    if (self.edgeStartPoint.x < self.width / 2.f) {
        return YES;
    }
    return NO;
}

#pragma mark - Handle WebView FindInPage Results

- (void)handleFindInPageWithComponents:(NSString *)url {
    NSDictionary *jsonDic = [url getWebViewJSONDicWithPrefix:@"native_findinpage://message?json="];
    if (jsonDic) {
        NSNumber *totalResults = [jsonDic cl_objectForKey:@"totalResults"];
        NSNumber *currentResult = [jsonDic cl_objectForKey:@"currentResult"];
        
        if (totalResults) {
            [CLMainVC findInPageDidUpdateTotalResults:[totalResults integerValue]];
        }
        if (currentResult) {
            [CLMainVC findInPageDidUpdateCurrentResult:[currentResult integerValue]];
        }
    }
}

#pragma mark - Handle ScreenEdgePan Gesture

- (void)addScreenEdgePanGesture{
    UIPanGestureRecognizer *edgeGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleScreenEdgePanGesture:)];
    self.gestureProxy = [[CLGestureProxy alloc] initWithCGPoint:CGPointMake(60, 0)];
    edgeGesture.delegate = _gestureProxy;
    edgeGesture.minimumNumberOfTouches = 1;
    edgeGesture.maximumNumberOfTouches = 1;
    
    [self addGestureRecognizer:edgeGesture];
}

- (void)handleScreenEdgePanGesture:(UIPanGestureRecognizer *)gesture{
    CGPoint point = [gesture locationInView:self];
    
    if (gesture.state == UIGestureRecognizerStateBegan) {
        self.backgroundColor = UIColorFromRGB(0x5A5A5A);
        [self setShowActivityViewIfNeeded];
        [self addArrowViewWithPoint:point];
        self.edgeStartPoint = point;
    } else if (gesture.state == UIGestureRecognizerStateChanged) {
        CGFloat offset = point.x - _edgeStartPoint.x;
        self.webView.transform = CGAffineTransformMakeTranslation(offset, 0);
        if (self.showActivityView && fabs(offset) >= kArrowActivitySize + 5.f * 2) {
            self.arrowActivityView.centerX = (offset > 0) ? offset / 2.0f : self.width - fabs(offset) / 2.0f;
            if (fabs(offset) > self.width / 2.0f - 50) {
                [self.arrowActivityView setOn:YES];
            }
            else{
                [self.arrowActivityView setOn:NO];
            }
        }
    } else {
        [UIView animateWithDuration:.2f animations:^{
           self.webView.transform = CGAffineTransformIdentity;
        } completion:^(BOOL finished) {
            self.backgroundColor = [UIColor clearColor];
            self.webView.bounds = CGRectMake(0, 0, self.width, self.height);
            self.webView.center = self.center;
            
            if (self.arrowActivityView.isOn) {
                WEAK_SELF;
                void (^block)(CLWebModel *prev, CLWebModel *cur) = ^(CLWebModel *prev, CLWebModel *cur) {
                    STRONG_SELF;
                    if (strongSelf) {
                        [strongSelf restoreWithCompletionHandler:nil animation:NO];
                    }
                };
                [self isWindowSwitchLeft] ? [[CLWebViewManager sharedInstance] switchToLeftWindowWithCompletion:block] : [[CLWebViewManager sharedInstance] switchToRightWindowWithCompletion:block];
            }
            [self removeArrowActivityView];
        }];
    }
}

#pragma mark - Handle WebView Long Press Gesture

- (void)handleContextMenuWithComponents:(NSString *)url{
    NSDictionary *jsonDic = [url getWebViewJSONDicWithPrefix:@"native_contextmenu://message?json="];
    if (jsonDic) {
        if (jsonDic[@"handled"]) {
            self.selectionGestureRecognizer.enabled = NO;
            self.selectionGestureRecognizer.enabled = YES;
        }
        
        NSString *urlString = jsonDic[@"link"];
        
        NSString *imageString = jsonDic[@"image"];
        
        [self handleContenxtMenuWithLink:urlString imageURL:imageString];
    }
}

- (void)handleContenxtMenuWithLink:(NSString *)link imageURL:(NSString *)image{
    NSURL *linkURL = [NSURL URLWithString:link];
    NSURL *imageURL = [NSURL URLWithString:image];
    if (!(linkURL || imageURL)) {
        return;
    }
    UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    
    NSString *dialogTitle;
    
    if (linkURL) {
        dialogTitle = linkURL.absoluteString;
        UIAlertAction *openNewTabAction = [UIAlertAction actionOpenNewTabWithCompletion:^{
            [self handleOpenInNewWindowWithURL:linkURL];
        }];
        [actionSheetController addAction:openNewTabAction];
        
        UIAlertAction *copyAction = [UIAlertAction actionCopyLinkWithURL:linkURL];
        [actionSheetController addAction:copyAction];
    }
    
    if (imageURL) {
        dialogTitle = imageURL.absoluteString;
        PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
        
        UIAlertAction *saveImageAction = [UIAlertAction actionWithTitle:@"保存图片" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
            if (status == PHAuthorizationStatusAuthorized || status == PHAuthorizationStatusNotDetermined) {
                [[CLMainVC navigationController].view showHUDAtBottomWithMessage:@"正在保存"];
                [self getImageWithURL:imageURL completion:^(UIImage *image, NSError *error){
                    if (image) {
                        [[CLMainVC navigationController].view showHUDAtBottomWithMessage:@"保存成功"];
                        UIImageWriteToSavedPhotosAlbum(image, nil, nil, NULL);
                    }
                }];
            } else {
                UIAlertController *accessDenied = [UIAlertController alertControllerWithTitle:@"CLBrowser 想要访问照片" message:@"将允许图片保存到照片" preferredStyle:UIAlertControllerStyleAlert];
                
                UIAlertAction *dismissAction = [UIAlertAction actionDismiss];
                [accessDenied addAction:dismissAction];
                
                UIAlertAction *settingsAction = [UIAlertAction actionSettings];
                [accessDenied addAction:settingsAction];
                
                [CLMainVC presentViewController:accessDenied animated:YES completion:nil];
            }
        }];
        [actionSheetController addAction:saveImageAction];
    }
    
    actionSheetController.title = [dialogTitle ellipsizeWithMaxLength:kActionSheetTitleMaxLength];
    UIAlertAction *cancelAction = [UIAlertAction actionDismiss];
    [actionSheetController addAction:cancelAction];
    
    if (!CLMainVC.presentedViewController) {
        [CLMainVC presentViewController:actionSheetController animated:YES completion:nil];
    }
}

- (void)getImageWithURL:(NSURL *)url completion:(void (^)(UIImage *, NSError *))completion{
    if (!(url && completion)) {
        return;
    }
    
    UIImage *image = nil;
    
    if ((image = [[NSURLCache sharedURLCache] getCachedImageWithURL:url])) {
        completion(image, nil);
        return;
    }
    
    [[CLHTTPClient sharedInstance] getImageWithURL:url completion:^(UIImage *image, NSError *error){
        if (image) {
            completion(image, nil);
        }
        else{
            completion(nil, error);
        }
    }];
}

#pragma mark - CLWebBottomBarClickDelegate

- (void)browserBottomToolBarButtonClickedWithTag:(CLBottomToolBarTag)tag{
    switch (tag) {
        case CLBottomToolBarTagForward:
        {
            [self removeHomePageIfNeededWithWebView:self.webView url:self.webView.request.URL needsEqual:YES];
            [self.webView goForward];
            break;
        }
        case CLBottomToolBarTagBack:
        {
            [self removeHomePageIfNeededWithWebView:self.webView url:self.webView.request.URL needsEqual:YES];
            [self.webView goBack];
            break;
        }
        case CLBottomToolBarTagRefresh:
        {
            NSURL *url = self.webView.request.URL;
            if ([url isErrorPageURL]) {
                NSURL *url = [self.webView.request.URL originalURLFromErrorURL];
                [self startLoadWithWebView:self.webView url:url];
            }
            else if (!url || [url.absoluteString isEqualToString:@""]){
                CLWebModel *webModel = [[CLWebViewManager sharedInstance] getCurrentWebModel];
                url = [NSURL URLWithString:webModel.url];
                [self startLoadWithWebView:self.webView url:url];
            }
            else {
                [self.webView reload];
            }
            break;
        }
        case CLBottomToolBarTagStop:
            [self.webView stopLoading];
            break;
        case CLBottomToolBarTagNovel:
        {
            [CLSharedAppDelegate.engine.navigationChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
                
            }];
            UIViewController *vc = [[FlutterViewController alloc]initWithEngine:CLSharedAppDelegate.engine nibName:nil bundle:nil];
            [CLNavigationService presentViewController:vc animated:YES completion:nil];
//            CLTabBarController *tabVc = [[CLTabBarController alloc]init];
//            [CLNavigationService pushController:tabVc animated:YES];
        }
            break;
        default:
            break;
    }
}

#pragma mark - WebViewDelegate

- (BOOL)webView:(CLWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    if (webView == self.webView) {
        NSURLComponents *url = [NSURLComponents componentsWithString:request.URL.absoluteString];
        if ([url.scheme isEqualToString:@"native_error"] && [url.host isEqualToString:@"reload"]) {
            [self browserBottomToolBarButtonClickedWithTag:CLBottomToolBarTagRefresh];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_sessionrestore"] && [url.host isEqualToString:@"reload"]){
            //session restore, just reload
            [webView reload];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_contextmenu"]){
            [self handleContextMenuWithComponents:url.string];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_findinpage"]){
            [self handleFindInPageWithComponents:url.string];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"about"] && [url.path isEqualToString:@"homepage"]) {
            [self handleHomePageWithWebView:webView];
            return YES;
        }
        else if ([url.scheme isEqualToString:@"http"] || [url.scheme isEqualToString:@"https"]) {
            return YES;
        }
        else if ([CLHttpHelper canAppHandleURL:request.URL]) {
            return url.host != nil;
        }// return NO that can't handle
        else {
            return NO;
        }
    }
    return YES;
}

- (BOOL)webView:(CLWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    NSURLRequest * request = webView.request;
    if (webView == self.webView) {
        NSString *urlString = request.URL.absoluteString;
        NSURLComponents *url = [NSURLComponents componentsWithString:urlString];
        if ([url.scheme isEqualToString:@"native_error"] && [url.host isEqualToString:@"reload"]) {
            [self browserBottomToolBarButtonClickedWithTag:CLBottomToolBarTagRefresh];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_sessionrestore"] && [url.host isEqualToString:@"reload"]){
            //session restore, just reload
            [webView reload];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_contextmenu"]){
            [self handleContextMenuWithComponents:url.string];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"native_findinpage"]){
            [self handleFindInPageWithComponents:url.string];
            return NO;
        }
        else if ([url.scheme isEqualToString:@"about"] && [url.path isEqualToString:@"homepage"]) {
            [self handleHomePageWithWebView:webView];
            return YES;
        }
        else if ([url.scheme isEqualToString:@"http"] || [url.scheme isEqualToString:@"https"]) {
            return YES;
        }
        else if ([CLHttpHelper canAppHandleURL:request.URL]) {
            return url.host != nil;
        }// return NO that can't handle
        else {
            return NO;
        }
    }
    return YES;
}
#pragma mark - CLBrowserLoadURLDelegate

- (void)browserContainerViewLoadWebViewWithSug:(NSString *)text{
    if (!text || !text.length) {
        return;
    }
    
    NSString *urlString = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    if (![CLHttpHelper isURL:urlString]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        urlString = [NSString stringWithFormat:BAIDU_SEARCH_URL,[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
#pragma clang diagnostic pop
    }
    else{
        if (![urlString isHTTPProtocol]) {
            urlString = [NSString stringWithFormat:@"http://%@",urlString];
        }
    }
    
    NSURL *url = [NSURL URLWithString:urlString];
    [self startLoadWithWebView:self.webView url:url];
}

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    if (@available(iOS 11.0, *)) {
        if ([NSStringFromClass([otherGestureRecognizer.delegate class]) containsString:@"_UIKeyboardBasedNonEditableTextSelectionGestureCluster"]) {
            self.selectionGestureRecognizer = otherGestureRecognizer;
        }
    }
    else if ([NSStringFromClass([otherGestureRecognizer.delegate class]) containsString:@"_UIKeyboardBasedNonEditableTextSelectionGestureController"]){
        self.selectionGestureRecognizer = otherGestureRecognizer;
    }
    if ([otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
        return [NSStringFromClass([otherGestureRecognizer.delegate class]) containsString:@"UICLBrowserView"];
    }
    
    return NO;
}

#pragma mark - Validating Commands

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    if (action == @selector(menuHelperFindInBaidu)) {
        return YES;
    }
    if (action == @selector(menuHelperFindInPage)) {
        return YES;
    }
    return [super canPerformAction:action withSender:sender];
}

- (void)findWithText:(NSString *)text function:(NSString *)function{
    text = (text.length) ? text : @"";
    
    NSString *escaped = [[text stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
    
    escaped = (escaped) ? escaped : @"";
    
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"window.cl.%@(\"%@\")",function,escaped] completionHandler:nil];
}

#pragma mark - MenuHelperInterface Protocol

- (void)menuHelperFindInPage{
    WEAK_SELF;
    
    [self getWebViewSelectionWithCompletion:^(NSString *result){
        [weakSelf findWithText:result function:@"find"];
        [CLMainVC findInPageDidSelectForSelection:result];
    }];
}

- (void)menuHelperFindInBaidu{
    WEAK_SELF;
    [self getWebViewSelectionWithCompletion:^(NSString *result){
        STRONG_SELF;
        if (strongSelf) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            result = [kBaiduSearchPath stringByAppendingString:[result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
#pragma clang diagnostic pop
            NSURL *url = [NSURL URLWithString:result];
            [strongSelf handleOpenInNewWindowWithURL:url];
        }
    }];
}

- (void)getWebViewSelectionWithCompletion:(void(^)(NSString *result))completion{
    WEAK_SELF;
    [self.webView evaluateJavaScript:@"window.cl.getSelection()" completionHandler:^(NSString *result, NSError *error){
        STRONG_SELF;
        if (strongSelf && result.length > 0 && completion) {
            dispatch_main_safe_async(^{
                completion(result);
            });
        }
    }];
}

#pragma mark - FindInPageBarDelegate

- (void)findInPage:(CLFindInPageBar *)findInPage didTextChange:(NSString *)text{
    [self findWithText:text function:@"find"];
}

- (void)findInPage:(CLFindInPageBar *)findInPage didFindPreviousWithText:(NSString *)text{
    [self findWithText:text function:@"findPrevious"];
}

- (void)findInPage:(CLFindInPageBar *)findInPage didFindNextWithText:(NSString *)text{
    [self findWithText:text function:@"findNext"];
}

- (void)findInPageDidPressClose:(CLFindInPageBar *)findInPage{
    [self.webView evaluateJavaScript:@"window.cl.findDone()" completionHandler:nil];
}

#pragma mark - Dealloc

- (void)dealloc{
    [Notifier removeObserver:self name:kOpenInNewWindowNotification object:nil];
}

@end
